package com.syc.springsecuritydemo1.config;

import com.syc.springsecuritydemo1.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * 开启权限注解 @EnableGlobalMethodSecurity()
 * securedEnabled = true 角色匹配
 * prePostEnabled = true 权限匹配（方法执行前、方法执行后）
 */
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /*@Autowired
    private MyAccessDeniedHandler accessDeniedHandler;*/
    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PersistentTokenRepository tokenRepository;

    /**
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //表单登录
        http.formLogin()
                //自定义登录页面
                .loginPage("/login")
                //自定义登录逻辑
                //.loginProcessingUrl("/login")
                //登录成后跳转的页面,必须是post(请求转发的方式)
                .successForwardUrl("/toIndex")
                //自定义登录成功后的逻辑
                //.successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
                //登录失败后跳转的页面，必须是post
                //.failureForwardUrl("/toError")
                //自定义登录失败后的逻辑
                .failureHandler(new MyAuthenticationFailureHandler("/toError"))
                /*//自定义登录用户名参数
                .usernameParameter("phone")*/;
        //授权
        http.authorizeRequests()
                //放行登录页面
                .antMatchers("/login").permitAll()
                .antMatchers("/error.html").permitAll()
                //放行静态文件
                .antMatchers("/image/**").permitAll()
                //指定某个页面需要某个权限
                .antMatchers("/admin.html").hasAnyAuthority("admin1")
                //所有的请求都需要认证
                .anyRequest().authenticated();
        //根据用户访问地址，动态判断登录用户是否具有权限
        //.anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");

        http.exceptionHandling()
                //自定义未授权异常处理 403异常
                .accessDeniedHandler(new MyAccessDeniedHandler());
        //记住我
        http.rememberMe()
                //自定义记住我参数名
                .rememberMeParameter("rememberMe")
                //自定义失效时间(默认记录时间为两周)
                //.tokenValiditySeconds()
                //自定义功能实现逻辑
                //.rememberMeServices()
                //自定义的登录逻辑
                .userDetailsService(userService)
                //指定存储位置
                .tokenRepository(tokenRepository);
        /*//退出登录  不设置会有 http://127.0.0.1:8080/login.html?logout
        http.logout()
                //退出登录url
                .logoutUrl("")
                //退出登录跳转url
                .logoutSuccessUrl("");*/
        //关闭跨站请求伪造
        //http.csrf().disable();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public PersistentTokenRepository tokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        //设置数据源
        jdbcTokenRepository.setDataSource(dataSource);
        //启动时是否创建表（第一次运行时开启，之后注释）
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }
}
